﻿unit GenericCollections;

interface

type
  /// <summary>
  /// Generic list.
  /// </summary>
  IList<T> = interface
    function Add(const Value: T): Integer;
    procedure Clear;
    function GetCount: Integer;
    property Count: Integer read GetCount;
    function GetItem(Index: Integer): T;
    procedure SetItem(Index: Integer; const Value: T);
    property Items[Index: Integer]: T read GetItem write SetItem; default;
  end;

  /// <summary>
  /// My naïve implemetation of IList&lt;T&gt;
  /// </summary>
  TList<T> = class(TInterfacedObject, IList<T>)
  strict private
    FItems: array of T;
    function GetCount: Integer;
    // procedure SetCount(Value: Integer);
    function GetItem(Index: Integer): T;
    procedure SetItem(Index: Integer; const Value: T);
  public
    constructor Create;
    destructor Destroy; override;

    // implementing IList<T>
    function Add(const Value: T): Integer;
    procedure Clear;
    property Count: Integer read GetCount; // write SetCount;
    property Items[Index: Integer]: T read GetItem write SetItem; default;
  end;

implementation

uses
  SysUtils, RTLConsts;

{ TList<T> }

function TList<T>.Add(const Value: T): Integer;
var
  ActLength: Integer;
begin
  ActLength := Length(FItems);
  SetLength(FItems, ActLength + 1);
  FItems[ActLength] := Value;
  Result := ActLength;
end;

procedure TList<T>.Clear;
begin
  // SetLength(FItems, 0);
  FItems := nil;
end;

constructor TList<T>.Create;
begin
  Clear;
  inherited Create;
end;

destructor TList<T>.Destroy;
begin

  inherited Destroy;
end;

function TList<T>.GetCount: Integer;
begin
  Result := Length(FItems);
end;

function TList<T>.GetItem(Index: Integer): T;
begin
  if (Index < 0) or (Index >= Count) then
    raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
  Result := FItems[Index];
end;

procedure TList<T>.SetItem(Index: Integer; const Value: T);
var
  OldItem: T;
begin
  if (Index < 0) or (Index >= Count) then
    raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);

  OldItem := FItems[Index];
  FItems[Index] := Value;
end;

end.
